<?php

/**
 * Created by PhpStorm.
 * User: GadflyBSD
 * Date: 16/3/14
 * Time: 16:33
 */
class PublicModel extends Model{
	protected $model;
	protected $replace = NULL;
	protected $cacheName;
	protected $ganged;
	protected $unite;
	protected $association;
	protected $site;
	protected $message;

	public function __construct(){
		$this->cacheName = C('NAME_EXPIRE').'Cache';
		foreach($this->getCache() AS $key => $val){
			$this->$key = $val;
		}
	}

	/**
	 * 获取当前模块的用户信息
	 * @param bool $refresh     是否强制刷新ß
	 *
	 * @return mixed
	 */
	public function getSession($refresh=false, $openid=null, $token=null){
		$param = $this->getParam();
		if($refresh){
			$session = session(strtolower($param['weixin']));
			if(is_null($openid)){
				$openid = $session['openid'];
			}else{
				$openid = $openid;
			}
			if(is_null($token))
				$userInfo = $session['userInfo'];
			else
				$userInfo = $token;
			$sideInfo = $this->auth2user($openid);
			$sideInfo['data']['errcode'] = '0';
			if(strtolower($param['weixin']) == 'wkshop')
				$sideInfo['data']['qrcodeUrl'] = U('Business/qrcode', array('s' => $sideInfo['data']['md5key']));
			session(strtolower($param['weixin']), array(
				'openid'    => $openid,
				'sideInfo'  => $sideInfo['data'],
				'userInfo'  => $userInfo,
			));
		}
		return array_merge(array('errcode' => '0'), session(strtolower($param['weixin'])));
	}

	/**
	 * 获取当前模块的微信标识/session标识和当前用户的openid
	 * @return array
	 */
	public function getParam(){
		switch(MODULE_NAME){
			case 'Business':
				$session = session('wkshop');
				return array('weixin' => 'WKSHOP', 'openid' => $session['openid']);
			case 'Customer':
				$session = session('waka');
				return array('weixin' => 'WAKA', 'openid' => $session['openid']);
			case 'Webapp':
				$session = session('wkapp');
				return array('weixin' => 'WKAPP', 'openid' => $session['openid']);
			default:
		}
	}

	/**
	 * 乐享哇咔微信 订阅行为响应和自动回复消息
	 * @throws Exception
	 */
	public function replay($param, $sendNews, $locationUrl=null, $type=false){
		$param = (is_array(strtoupper($param), array('WAKA', 'WKSHOP', 'WKAPP')))?strtoupper($param):'WAKA';
		$locationUrl = (is_null($locationUrl))?APP_URL.U(MODULE_NAME.'/WxIndex', array('an' => 'bindWeixin')):$locationUrl;
		Vendor('Weixin');
		$weixin = new Weixin($param);
		if($type){
			$weixin->valid();
		}else{
			if($weixin->checkSignature()){
				$data = $weixin->request();
				if($data && is_array($data)){
					if($data['MsgType'] == 'event' && $data['Event'] == 'unsubscribe')
						$this->attention($data['FromUserName'], 'unsubscribe', $param);
					else
						$this->attention($data['FromUserName'], 'subscribe', $param);
					switch($data['MsgType']){
						case 'text':
							$weixin->response($sendNews, 'news');
							break;
						case 'image':
							$weixin->response($sendNews, 'news');
							break;
						case 'voice':
							$weixin->response($sendNews, 'news');
							break;
						case 'video':
							$weixin->response($sendNews, 'news');
							break;
						case 'event':
							switch($data['Event']){
								case 'subscribe':
									$weixin->response($sendNews, 'news');
									header("Location: ".$locationUrl);
									break;
								case 'unsubscribe':
									break;
							}
							break;
					}
				}
			}
		}
	}

	/**
	 * 用户关注微信号后创建用户资料
	 * @param $openid
	 *
	 * @return array
	 */
	public function attention($openid, $type = 'subscribe'){
		$type = defaultParam($type, array('subscribe', 'unsubscribe'), 'subscribe');
		if($type == 'subscribe'){
			return $this->auth2user($openid);
		}
	}

	public function auth2user($openid){
		Vendor('Weixin');
		$param = $this->getParam();
		$weixin = new Weixin($param['weixin']);
		if($param['weixin'] != 'WKAPP'){
			if(M('WangkaUser')->where('openid="'.$openid.'"')->count() == 0){
				$data = $weixin->get_openid_info($openid);
				$state = $this->getCache('userState_subscribe');
				switch($data['sex']){
					case '1':
						$gander = $this->getCache('gander_male');
						break;
					case '2':
						$gander = $this->getCache('gander_female');
						break;
					default:
						$gander = $this->getCache('gander_unknown');
						break;
				}
				$open = array(
					'weixin'        => strtolower($param['weixin']),
					'openid'        => $openid,
					'nickname'      => $data['nickname'],
					'gander'        => $gander['id'],
					'headimgurl'    => $data['headimgurl'],
					'last_changes'  => 'subscribe',
					'recip'         => get_client_ip(),
					'state'         => $state['id'],
				);
				if(!M('WangkaUser')->add($open))
					return array('errcode' => '30001');
			}
		}else{
			if(M('Weixin')->where('openid="'.$openid.'"')->count() == 0){
				$data = $weixin->get_openid_info($openid);
				$state = $this->getCache('userState_subscribe');
				switch($data['sex']){
					case '1':
						$gander = $this->getCache('gander_male');
						break;
					case '2':
						$gander = $this->getCache('gander_female');
						break;
					default:
						$gander = $this->getCache('gander_unknown');
						break;
				}
				$open = array(
					'weixin'        => strtolower($param['weixin']),
					'openid'        => $openid,
					'nickname'      => $data['nickname'],
					'gander'        => $gander['id'],
					'headimgurl'    => $data['headimgurl'],
					'last_changes'  => 'subscribe',
					'recip'         => get_client_ip(),
					'state'         => $state['id'],
				);
				if(!M('Weixin')->add($open))
					return array('errcode' => '30001');
			}
		}
		switch($param['weixin']){
			case 'WKSHOP':
				$data = M('WangkaBindView')->where('openid="'.$openid.'"')->find();
				break;
			case 'WAKA':
				$data = M('WakaBindView')->where('openid="'.$openid.'"')->find();
				break;
			case 'WKAPP':
				$data = M('WkappBindView')->where('openid="'.$openid.'"')->find();
				break;
		}
		return array('errcode' => '0', 'data' => $data);
	}

	/**
	 * 递归获得分类信息
	 *
	 * @table string        // 分类表名(驼峰写法)
	 * @catid int           // 从分类id开始,默认0为从根开始展现
	 * @item  int           // 从第几级显示默认0
	 * @return array
	 *
	 * 分类表数据结构:
	DROP TABLE IF EXISTS `pre_category`;
	CREATE TABLE `pre_category` (
		`catid` INTEGER(11) NOT NULL AUTO_INCREMENT,
		`upid` INTEGER(11) NOT NULL DEFAULT '0' COMMENT '上级分类id, 顶级分类ID为0',
		`catname` VARCHAR(20) NOT NULL COMMENT '分类名称',
		`keyname` VARCHAR(20) NOT NULL COMMENT '查询关键字',
		`displayorder` int(10) DEFAULT '0' COMMENT '分类排序',
		PRIMARY KEY (`id`)
	) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT '分类列表';
	 *
	 */
	public function getCategory($table, $catid = 0, $item = 0){
		$param['catid'] = (is_null($catid))?0:$catid;
		$param['item'] = (is_null($item))?0:$item;
		$flag = '&nbsp;';
		for($i=0; $i<$param['item']; $i++){
			$flag .= '&nbsp;&nbsp;&nbsp;&nbsp;';
		}
		$flag .= '+--';
		$data = M($table);
		$list = $data->where('upid = '.$param['catid'])->order('displayorder ASC')->select();
		foreach($list AS $k => $v){
			$count = $data->where('upid='.$v['catid'])->count();
			$option[] = array(
				'catid'     => $v['catid'],
				'catname'   => $flag.$v['catname'],
				'keyname'   => $v['keyname'],
			);
			if($v['upid'] != 0){
				$angular[] = array(
					'catid'     => $v['catid'],
					'catname'   => $v['catname'],
					'optgroup'  => $data->where('catid='.$v['upid'])->getField('catname'),
				);
			}
			$json[] = array_merge($v, array('open' => true));
			$array[$k] = $v;
			if($count>0){
				$Category = $this->getCategory($table, $v['catid'], ($param['item']+1));
				$option = array_merge_recursive($option, $Category['option']);
				$angular = (is_array($angular))?array_merge_recursive($angular, $Category['angular']):$Category['angular'];
				$json = array_merge_recursive($json, $Category['json']);
				$array[$k]['item'] = $Category['array'];
			}
		}
		return array(
			'option'    => $option,
			'angular'   => $angular,
			'json'      => $json,
			'array'     => $array,
		);
	}

	/**
	 * 返回一个angularJS所需要的ngOptions数据, 页面模板调用方法:
	 *
	 * HTML:
	<select name="categroy" ng-model="formData.categroy" required
			ng-options="cat.catname group by cat.optgroup for cat in categroy track by cat.catid">
		<option selected value="">请选择分类</option>
	</select>
	 * JavaScript:
	$scope.categroy = resp.data;
	 *
	 * @param     $table    数据库表名(驼峰写法)
	 * @param int $upid     顶级upid值
	 *
	 * @return array
	 */
	public function getNgOptions($table, $upid=0){
		$data = array();
		if($upid==0){
			foreach(M($table)->where('upid=0')->select() AS $val){
				foreach(M($table)->where('upid='.$val['catid'])->select() AS $v){
					$data[] = array(
						'catid'     => $v['catid'],
						'catname'   => $v['catname'],
						'optgroup'  => M($table)->where('catid='.$v['upid'])->getField('catname'),
					);
				}
			}
		}else{
			$optgroup = M($table)->where('catid='.$upid)->getField('catname');
			foreach(M($table)->where('upid='.$upid)->select() AS $v){
				$data[] = array(
					'catid'     => $v['catid'],
					'catname'   => $v['catname'],
					'optgroup'  => $optgroup,
				);
			}
		}
		return array('errcode' => 0, 'data' => $data);
	}

	/**
	 * 获得站点数据列表
	 * @param $type
	 *
	 * @return null
	 */
	public function getSiteData($type){
		switch($type){
			case 'ganged':
				foreach(M('WangkaGanged')->where('state=1')->field('state', true)->select() AS $val){
					$return[$val['id']] = $val;
					$return['key'][] = $val['ckey'];
				}
				break;
			case 'unite':
				foreach(M('WangkaUnite')->where('state=1')->field('displayorder,state', true)->select() AS $val){
					$return[$val['id']] = $val;
				}
				break;
			case 'association':
				foreach(M('WangkaGanged')->where('state=1')->field('state', true)->select() AS $val){
					foreach(M('WangkaUnite')->where('state=1 AND gid='.$val['id'])->field('displayorder,state', true)->order('displayorder')->select() AS $vo){
						$return[$val['ckey']][$vo['ckey']] = $vo;
						$return[$val['ckey']]['key'][] = $vo['ckey'];
					}
				}
				break;
			case 'setting':
				$return = M('WangkaSetting')->select();
				break;
			case 'message':
				foreach(M('Message')->where('state=1')->field('state', true)->select() AS $val){
					$return[$val['errcode']] = $val['message'];
				}
				break;
		}
		return $return;
	}

	/**
	 * 获取服务器缓存数据，如果缓存不存在则缓存该数据。
	 * 用于在服务器上缓存、获取：Ganged、Unite、Func数据（以后还可以继续扩充Site、Func等数据）
	 *
	 * @param null $param     需要获取的数据名称，如果是NULL则返回所有缓存数据，不同数据类型和参数值获取到不同的缓存数据
	 *                          array类型形式：array('ganged' => 'ganged_ckey', ['unite' => 'unite_ckey'])可以获取到指定的gangedUnite数据列表；
	 *                          integer类型：根据具体unite_id获取相应的unite数据列表；
	 *                          string类型：
	 *                              ganged                  获取所有ganged数据列表
	 *                              unite                   获取所有unite数据列表
	 *                              association             获取所有gangedUnite关联数组数据列表
	 *                              func                    获取所有func数据列表
	 *                              gangedCkey              获取指定的ganged数据列表
	 *                              gangedCkey_uniteCkey    获取到指定的gangedUnite关联数组数据列表
	 *                              orther                  获取所有数据列表
	 *                          null类型：获取所有数据类型
	 * @param bool $refresh   是否刷新服务器缓存
	 *
	 * @return array|mixed|string|void      以数组形式返回该缓存数据
	 */
	public function getCache($param = null, $refresh = false){
		if(S('weixinCache') && APP_CACHE && !$refresh)
			$cache = S('weixinCache');
		else
			$cache = array(
				'ganged'        => $this->getSiteData('ganged'),
				'unite'         => $this->getSiteData('unite'),
				'association'   => $this->getSiteData('association'),
				'setting'       => $this->getSiteData('setting'),
				'message'       => $this->getSiteData('message'),
			);
		if(!APP_CACHE || !S('weixinCache') || $refresh) S('weixinCache', $cache);
		switch(gettype($param)){
			case 'array':
				if(in_array($param['ganged'], $cache['ganged']['key'])){
					if($param['unite'] && !is_null($param['unite']) && in_array($param['unite'], $cache['association'][$param['ganged']]['key']))
						return $cache['association'][$param['ganged']][$param['unite']];
					else
						return $cache['association'][$param['ganged']];
				}
			case 'integer':
				return $cache['unite'][$param];
			case 'string':
				switch($param){
					case 'ganged':
						return $cache['ganged'];
					case 'unite':
						return $cache['unite'];
					case 'association':
						return $cache['association'];
					case 'setting':
						return $cache['setting'];
					case 'message':
						return $cache['message'];
					default:
						$param = explode('_', $param);
						switch(count($param)){
							case 1:
								if(in_array($param[0], $cache['ganged']['key'])){
									unset($cache['association'][$param[0]]['key']);
									return $cache['association'][$param[0]];
								}else{
									return $cache;
								}
							case 2:
								if(in_array($param[0], $cache['ganged']['key'])){
									if(in_array($param[1], $cache['association'][$param[0]]['key'])){
										unset($cache['association'][$param[0]][$param[1]]['key']);
										return $cache['association'][$param[0]][$param[1]];
									}else{
										unset($cache['association'][$param[0]]['key']);
										return $cache['association'][$param[0]];
									}
								}else{
									return $cache;
								}
							default:
								return $cache;
						}
				}
			default:
				return $cache;
		}
	}

	public function curd($param = array()){
		$curd = array(
			'model'     => ($param['model'])?$param['model']:M(),
			'where'     => ($param['where'])?$param['where']:'id != 0',
			'field'     => ($param['field'])?$param['field']:true,
			'data'      => ($param['data'])?$param['data']:array(),
			'order'     => ($param['order'])?$param['order']:'',
		);
		$type = ($param['type'] && in_array($param['type'], array('addAll', 'add', 'save', 'delete', 'select', 'find')))?$param['type']:'select';
		switch($type){
			case 'addAll':
				$debug = array('data' => $curd['data'], 'insID' => array());
				$curd['model']->startTrans();
				foreach($curd['data'] AS $val){
					$add = $this->curd(array(
						'type'  => 'add',
						'model' => $curd['model'],
						'data'  => $val,
					));
					if($add['errcode'] == 0){
						$errcode = 0;
						array_push($debug['insID'], $add['pk']);
					}else{
						$errcode = 20001;
						break;
					}
				}
				if($errcode == 0){
					$curd['model']->commit();
					$return = array('errcode' => 0, 'pk' => $debug['insID'], 'ac' => 'InsertAll');
				}else{
					$curd['model']->rollback();
					$return = array('errcode' => $errcode);
				}
				break;
			case 'add':
				$recid = $curd['model']->add($curd['data']);
				$debug = array(
					'data'      => $curd['data'],
					'insID'     => $curd['model']->getLastInsID(),
					'sqlError'  => $curd['model']->getError(),
					'execute'   => $curd['model']->getLastSql(),
				);
				if($recid == $debug['insID'])
					$return = array('errcode' => 0, 'pk' => $recid, 'ac' => 'Insert');
				else
					$return = array('errcode' => 20001);
				break;
			case 'save':
				$recid = $curd['model']->where($curd['where'])->save($curd['data']);
				$debug = array(
					'data'      => $curd['data'],
					'where'     => $curd['where'],
					'sqlError'  => $curd['model']->getError(),
					'execute'   => $curd['model']->getLastSql(),
				);
				if($recid){
					$pk = $curd['model']->where($curd['where'])->getField($curd['model']->getPk());
					$return = array('errcode' => 0, 'pk' => $pk, 'ac' => 'update');
				}else{
					$return = array('errcode' => 20002);
				}
				break;
			case 'delete':
				$recid = $curd['model']->where($curd['where'])->delete();
				$debug = array(
					'where'     => $curd['where'],
					'sqlError'  => $curd['model']->getError(),
					'execute'   => $curd['model']->getLastSql(),
				);
				if($recid)
					$return = array('errcode' => 0, 'ac' => 'Delete');
				else
					$return = array('errcode' => 20003);
				break;
			case 'select':
				$data = $curd['model']->where($curd['where'])->order($curd['order'])->field($curd['field'])->select();
				$debug = array(
					'data'      => $data,
					'where'     => $curd['where'],
					'sqlError'  => $curd['model']->getError(),
					'execute'   => $curd['model']->getLastSql(),
				);
				if(!$data)
					$return = array('errcode' => 20004);
				elseif(is_null($data))
					$return = array('errcode' => 20005);
				else
					$return = array('errcode' => 0);
				break;
			case 'find':
				$data = $curd['model']->where($curd['where'])->field($curd['field'])->find();
				$debug = array(
					'data'      => $data,
					'where'     => $curd['where'],
					'sqlError'  => $curd['model']->getError(),
					'execute'   => $curd['model']->getLastSql(),
				);
				if(!$data)
					$return = array('errcode' => 20004);
				elseif(is_null($data))
					$return = array('errcode' => 20005);
				else
					$return = array('errcode' => 0);
				break;
			default:
				$return = array('errcode' => 20000);
				$debug = array();
		}
		return array_merge($return, $debug);
	}

	public function add($data='',$options=array(), $replace=false){
		if(parent::add($data, $options, $replace))
			return array(
				'errcode'   => 0,
				'data'      => $data,
				'insID'     => $this->getLastInsID(),
			);
		else
			return array(
				'errcode'   => 20001,
				'data'      => $data,
				'sqlError'  => $this->getError(),
				'dbError'   => $this->getDbError(),
				'execute'   => $this->getLastSql(),
			);
	}

	/**
	 * 数据库写操作封装模型
	 * @param       $action     数据库写操作类型，可以是insert、add、update、edit、delete、del
	 * @param array $query      数据库操作参数
	 *          $query['table']     数据操作的表名,默认为空则为当前模型所在表名
	 *          $query['where']     数据库写操作的条件语句，默认为NULL，当insert和add操作类型时无效，其他类型时的默认值为id='.I('post.id')
	 *          $query['validate']  数据字段验证方式或方法名，当类型为数组类型时采用ThinkPHP原生的模型自动验证方式，当类型为字符串时采用自定义方式验证（此时需定义以『字符串+Validate』为方法名的自定义验证方法）
	 *          $query['auto']      数据字段自动完成, 需要自动完成的一些数据,默认为一个空数组
	 * @param null  $callback   数据操作成功后的回调方法名，默认为空代表操作成功后不调用回调方法，当制定一个字符串时代表操作成功后调用相应的回调方法（此时需定义以『字符串+Callback』为方法名的自定义回调方法）
	 * @param null  $param      数据操作成功后调用的回调方法所需的参数，默认为空
	 *
	 * @return array
	 */
	protected function createToken($action, $query = array(), $callback = null, $param = null){
		$model = D(is_null($query['table'])?$this->name:$query['table']);
		$query['where'] = is_null($query['where'])?'id='.I('post.id'):$query['where'];
		$data = (I('post.'))?I('post.'):array();
		$post = (is_array($query['auto']))?array_merge($query['auto'], $data):$data;
		M()->startTrans();
		if(is_array($query['validate'])){
			$create = $model->validate($query['validate'])->create($post);
		}elseif(is_string($query['validate']) && method_exists($this, $query['validate'].'Validate')){
			$validate_return = call_user_func(array(&$this, $query['validate'].'Validate'));
			if($validate_return['type'] != 'error')
				$create = $model->create($post);
			else
				return $validate_return;
		}elseif(is_null($query['validate'])){
			$create = $model->create($post);
		}else{
			return array('type' => 'error', 'content' => '系统没有找到 '.$query['validate'].'Validate 方法', 'title' => '出错啦');
		}
		if($create){
			$token='';
			tag(create_token, $token);
			$public = array('token' => $token, 'replace' => $this->replace);
			switch($action){
				case 'insert':
				case 'add':
					$rec = $model->add();
					break;
				case 'update':
				case 'edit':
					$rec = $model->where($query['where'])->save();
					break;
				case 'delete':
				case 'del':
					$rec = $model->where($query['where'])->delete();
					break;
			}
			if($rec){
				if(!is_null($callback)){
					if(method_exists($this, $callback.'Callback')){
						if(is_null($param))
							call_user_func(array(&$this, $callback.'Callback'));
						else
							call_user_func(array(&$this, $callback.'Callback'), $param);
						$return = array('type' => 'success', 'content' => self::SQLSUCCESS, 'title' => '数据库写入操作成功!', 'recid' => $rec);
					}else{
						$return = array('type' => 'error', 'content' => '系统没有找到 '.$callback.'Callback 方法', 'title' => '出错啦');
					}
				}else{
					$return = array('type' => 'success', 'content' => self::SQLSUCCESS, 'title' => '数据库写入操作成功!', 'recid' => $rec);
				}
			}else{
				$return = array('type' => 'error', 'content' => self::SQLERROR, 'title' => '出错啦!', 'sql' => $model->getLastSql());
			}
		}else{
			$public = array('replace' => $this->replace);
			$return = array('type' => 'error', 'content' => $model->getError(), 'title' => '出错啦', 'data' => $post);
		}
		$this->debugLogger(array('return' => $return), $model);
		($return['type'] == 'success')?M()->commit():M()->rollback();
		return array_merge($return, $public);
	}

	/**
	 * 数据验证方法
	 * @param       $type
	 * @param       $value
	 * @param array $rule
	 *
	 * @return bool
	 */
	public function validator($type, $value, $rule=array()){
		if(is_array($type)){
			foreach($type AS $val){
				if($this->validator($val['type'], $val['value'], $val['rule']))
					return array('errcode' => $val['errcode']);
			}
			return true;
		}elseif(is_string($type)){
			switch($type){
				case 'require':
					return preg_match('/.+/', $value);
				case 'email':
					$preg = "/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/";
					return preg_match($preg, $value);
				case 'url':
					$preg = "/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/";
					return preg_match($preg, $value);
				case 'realname':
					if(utf8_strlen($value) > 5)
						return false;
					else
						return preg_match("/^([\x81-\xfe][\x40-\xfe]){4,10}/", $value);
				case 'mobile':
					return preg_match('/^1[3|4|5|7|8][0-9]\d{4,8}$/', $value);
				case 'password':
					$pattern = '/^[\@A-Za-z0-9\!\#\$\%\^\&\*\.\~]{6,16}$/';
					return (preg_match($pattern, $value))?true:false;
				case 'idcard':
					return validation_filter_id_card($value);
				case 'zip':
					return preg_match('/^\d{6}$/', $value);
				case 'chinese':
					return preg_match('/[\x7f-\xff]/', $value);
				case 'english':
					return preg_match('/^[A-Za-z]+$/', $value);
				case 'isBankSN':
					return preg_match('/^(\d{16}|\d{19})$/', $value);
				case 'number':
					return preg_match('/^\d+$/', $value);
				case 'integer':
					return preg_match("/^[0-9]*[1-9][0-9]*$/", $value);
				case 'double':
					return ($value>0 && preg_match("/^\\d+(\\.\\d+)?$/", $value));
				case 'in': // 验证是否在某个指定范围之内 逗号分隔字符串或者数组
				case 'notin':
					$range   = is_array($rule)? $rule : explode(',',$rule);
					return ($type == 'in')?(in_array($value ,$range)):(!in_array($value ,$range));
				case 'between':
				case 'notbetween': // 验证是否不在某个范围
					if (is_array($rule)){
						$min    =    $rule[0];
						$max    =    $rule[1];
					}else{
						list($min,$max)   =  explode(',',$rule);
					}
					return ($type == 'between')?($value>=$min && $value<=$max):($value<$min || $value>$max);
				case 'equal': // 验证是否等于某个值
				case 'notequal': // 验证是否等于某个值
					return ($type == 'equal')?($value == $rule):($value != $rule);
				case 'length': // 验证长度
					$length  =  mb_strlen($value,'utf-8'); // 当前数据长度
					if(strpos($rule,',')) { // 长度区间
						list($min,$max)   =  explode(',',$rule);
						return $length >= $min && $length <= $max;
					}else{// 指定长度
						return $length == $rule;
					}
				case 'min':
					if($this->validator('integer', $value)){
						if($rule != 0){
							if($rule > $value) return false;
						}
						return true;
					}
					return false;
				case 'max':
					if($this->validator('integer', $value)){
						if($rule != 0){
							if($rule < $value) return false;
						}
						return true;
					}
					return false;
				case 'reward':      //验证当前用户可用积分大于或等于 $value
					if($this->validator('integer', $value)){
						$money = $this->getSessionMoney();
						return ($money['reward'] < $value)?false:true;
					}
					return false;
				case 'account':     //验证当前用户可用余额大于或等于 $value
					if($this->validator('integer', $value)){
						$money = $this->getSessionMoney();
						return ($money['account'] < $value)?false:true;
					}
					return false;
				case 'experience':  //验证当前用户可用体验金大于或等于 $value
					if($this->validator('integer', $value)){
						$money = $this->getSessionMoney();
						return ($money['experience'] < $value)?false:true;
					}
					return false;
				case 'payPassword': //验证当前用户的支付密码
					$salt = M('UcenterMembers')->where('uid='.$this->getUid())->getField('salt');
					$count = M('ThinkMoney')->where('uid='.$this->getUid().' AND password = "'.md5(md5($value).$salt).'"')->count();
					return ($count == 1)?true:false;
				case 'unique':
					/**
					 * 验证数据唯一性
					 * @param   $rule['table']      所需验证的数据表名
					 * @param   $rule['filed']      所需验证的字段名
					 * @param   $value              所需验证的值
					 */
					if(M($rule['table'])->where($rule['field'].'="'.$value.'"')->count() == 0)
						return true;
					else
						return false;
				case 'smsCode':
					/**
					 * 验证能力平台短信验证码是否正确
					 * @param   $value  array   所需验证的手机号码和短信验证码数组形如: array('mobile' => 13355556666, 'code' => 123456)
					 * @param   $rule   string  默认验证后不正确的情况下注销该验证码的有效性,只有在验证通过的情况下才注销验证码有效性; 当为"refresh"的时候,无论成功与否都注销该验证码的有效性
					 */
					$SmsCode = session('SmsCode');
					if(is_array($value)){
						if($value['mobile'] == $SmsCode['mobile'] && $value['code'] == $SmsCode['code'] && $SmsCode['timestamp'] > time()){
							session('SmsCode', null);
							return true;
						}else{
							if($rule = 'refresh')
								session('SmsCode', null);
							return false;
						}
					}else{
						if($value == $SmsCode['code'] && $SmsCode['timestamp'] > time()){
							session('SmsCode', null);
							return true;
						}else{
							if($rule = 'refresh')
								session('SmsCode', null);
							return false;
						}
					}
				case 'verifyImg':
					return (session('verify') == md5($value))?true:false;
			}
		}
	}

	/**
	 * 通过CURL或者封装过的Snoopy方式像微信服务器发送指令,GET或者POST方法提交数据返回结果
	 * @param        $url       提交数据的接收地址,如果是GET方法,该地址不包含?后的数据
	 * @param        $data      提交的数据GET方式为?后的部分,POST为一个表单的JSON数据
	 * @param string $method    数据提交的方法,GET(默认)或者POST
	 * @param bool   $ssl       是否SSL加密,默认为True
	 *
	 * @return string   返回服务器返回的结果
	 */
	protected function curlData($url, $data, $method='GET', $ssl=true){
		switch($method){
			case 'GET':
				$getUrl = $url.'?'.$data;
				$ch = curl_init($getUrl);
				curl_setopt($ch, CURLOPT_URL,$getUrl);
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
				break;
			case 'POST':
				$ch = curl_init($url);
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
				curl_setopt($ch, CURLOPT_POST, 1);
				curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
				break;
		}
		curl_setopt($ch, CURLOPT_TIMEOUT, 500);
		if($ssl){
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
		}
		$results= curl_exec($ch);
		curl_close($ch);
		return $results;
	}

	public function getMedia($url, $target){
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_HEADER, 0);
		curl_setopt($ch, CURLOPT_NOBODY, 0);    //对body进行输出。
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		$package = curl_exec($ch);
		$httpinfo = curl_getinfo($ch);
		curl_close($ch);
		$media = array_merge(array('mediaBody' => $package), $httpinfo);
		$filename = uploadName($url);
		$targetPath = $target.date('/Ym/d/');
		if(!file_exists(realpath('../static/').$targetPath))
			mkdirs(realpath('../static/').$targetPath, 0755, true);
		if(file_put_contents(realpath('../static/').$targetPath.'/'.$filename, $media['mediaBody']) > 0)
			return array('type' => 'success', 'content' => '文件写入成功!', 'url' => $targetPath.$filename);
		else
			return array('type' => 'error', 'content' => '文件写入错误, 请与管理员联系!');
	}

}